/**
 * 奇思妙绘API客户端 - 改进版Discord图片下载器
 * 自动从服务器获取待下载的任务，下载高清Discord图片并处理
 */
/**
 * 用户认证和信息相关路由
 */
const axios = require('axios');
const fs = require('fs');
const path = require('path');
const puppeteer = require('puppeteer');
const FormData = require('form-data');

// 配置
const SERVER_API_BASE_URL = 'http://121.37.154.212'; // 服务器地址
const API_KEY = 'qsmhsecureapikey20240601'; // API密钥
const DOWNLOAD_DIR = path.join(__dirname, 'downloads'); // 下载目录
const POLL_INTERVAL = 3000; // 轮询间隔(毫秒)
const CLEANUP_INTERVAL = 60 * 60 * 1000; // 清理间隔(1小时)
const MAX_FILE_AGE = 6 * 60 * 60 * 1000; // 最大文件保存时间(6小时)
const LOG_FILE = path.join(__dirname, 'downloader.log'); // 日志文件

// 确保下载目录存在
if (!fs.existsSync(DOWNLOAD_DIR)) {
  fs.mkdirSync(DOWNLOAD_DIR, { recursive: true });
}

// 创建简单的日志函数
const log = (message) => {
  const timestamp = new Date().toISOString();
  const logMessage = `[${timestamp}] ${message}`;
  console.log(logMessage);
  fs.appendFileSync(LOG_FILE, logMessage + '\n');
};

log('改进版Discord图片下载器启动');

// 创建HTTP客户端
const apiClient = axios.create({
  baseURL: SERVER_API_BASE_URL,
  headers: { 'x-api-key': API_KEY }
});

// 从服务器获取待下载的任务
async function getPendingTasks() {
  try {
    log('发送获取任务请求到服务器...');
    const response = await apiClient.get('/api/local-downloader/pending-tasks');
    
    log(`服务器响应状态: ${response.status}`);
    log(`响应数据: ${JSON.stringify(response.data).substring(0, 300)}...`);
    
    // 检查响应中是否包含task字段
    if (response.data && response.data.task) {
      log('找到单个任务对象');
      return [response.data.task]; // 返回任务数组，以便处理
    }
    
    // 返回响应中的tasks字段，如果不存在则返回空数组
    if (response.data && response.data.tasks) {
      log(`找到${response.data.tasks.length}个任务`);
      return response.data.tasks;
    }
    
    // 如果响应直接是个对象且有taskId，将其作为单个任务返回
    if (response.data && response.data.success && response.data.task) {
      log('找到单个任务对象，格式为response.data.task');
      return [response.data.task];
    }
    
    log('未找到任务，返回空数组');
    return [];
  } catch (error) {
    log(`获取任务失败: ${error.message}`);
    if (error.response) {
      log(`错误状态码: ${error.response.status}`);
      log(`错误响应数据: ${JSON.stringify(error.response.data)}`);
    } else if (error.request) {
      log('已发送请求但没有收到响应');
    } else {
      log(`请求配置错误: ${error.message}`);
    }
    return [];
  }
}

// 使用改进的方法从Discord下载高清图片
async function downloadDiscordImage(imageUrl, taskId) {
  if (!imageUrl || !imageUrl.includes('cdn.discordapp.com')) {
    throw new Error('无效的Discord图片URL');
  }

  log(`[${taskId}] 开始下载Discord高清图片: ${imageUrl}`);
  const outputPath = path.join(DOWNLOAD_DIR, `task_${taskId}_${Date.now()}.png`);

  try {
    // 更新任务状态为正在下载
    await updateTaskStatus(taskId, 'downloading', 96, '正在下载Discord高清图片');

    // 启动浏览器
    const browser = await puppeteer.launch({
      headless: true,
      args: ['--no-sandbox', '--disable-setuid-sandbox']
    });

    const page = await browser.newPage();
    
    // 设置更大的视口以确保加载高质量图片
    await page.setViewport({ width: 2048, height: 2048 });
    
    // 设置请求拦截以记录所有图片URL
    let imageUrls = [];
    await page.setRequestInterception(true);
    page.on('request', request => {
      const url = request.url();
      if (request.resourceType() === 'image' && url.includes('discord')) {
        imageUrls.push(url);
      }
      request.continue();
    });
    
    // 导航到图片URL
    await page.goto(imageUrl, { waitUntil: 'networkidle0', timeout: 60000 });
    
    // 等待图片加载
    await page.waitForSelector('img', { timeout: 10000 });
    
    // 获取Discord原始图片URL (改进的方法)
    const originalImageUrl = await page.evaluate(() => {
      // 方法1: 尝试查找下载链接或原始图片链接
      const downloadLinks = Array.from(document.querySelectorAll('a')).filter(el => 
        el.textContent.includes('下载') || 
        el.textContent.includes('原图') || 
        el.textContent.includes('Download') || 
        el.textContent.includes('Original')
      );
      
      if (downloadLinks.length > 0) {
        return downloadLinks[0].href;
      }
      
      // 方法2: 查找所有图片，优先获取原始尺寸图片
      const images = Array.from(document.querySelectorAll('img'));
      
      // 查找特定的原始图片属性或数据属性
      const originalImage = images.find(img => 
        img.getAttribute('data-original') || 
        img.getAttribute('data-src-original') || 
        (img.src && img.src.includes('?format=original'))
      );
      
      if (originalImage) {
        return originalImage.getAttribute('data-original') || 
               originalImage.getAttribute('data-src-original') || 
               originalImage.src;
      }
      
      // 方法3: 查找最大的图片并修改URL参数以获取原图
      const largestImage = images.sort((a, b) => {
        const areaA = a.width * a.height;
        const areaB = b.width * b.height;
        return areaB - areaA;
      })[0];
      
      if (largestImage) {
        let url = largestImage.src;
        
        // 修改Discord URL以获取高清版本
        if (url.includes('discord') && !url.includes('?format=')) {
          // 移除已有的尺寸限制参数
          url = url.replace(/\?width=\d+&height=\d+/, '');
          // 添加原始格式参数
          url = url.includes('?') ? `${url}&format=original` : `${url}?format=original`;
        }
        
        return url;
      }
      
      return null;
    });
    
    // 如果页面内没找到合适的原图URL，就用拦截到的图片URLs中分辨率最高的
    let finalImageUrl = originalImageUrl;
    
    if (!finalImageUrl && imageUrls.length > 0) {
      log(`[${taskId}] 页面内未找到原图链接，正在分析拦截到的${imageUrls.length}个图片URLs`);
      
      // 对拦截到的URLs进行分析，选择最可能是高清版本的
      finalImageUrl = imageUrls
        .filter(url => url.includes('discord') && !url.includes('avatar') && !url.includes('emoji'))
        .sort((a, b) => {
          // 尝试通过URL判断图片质量 (通常?width=和?size=参数较大的是高清版)
          const getSizeParam = (url) => {
            const widthMatch = url.match(/width=(\d+)/);
            const sizeMatch = url.match(/size=(\d+)/);
            return (widthMatch ? parseInt(widthMatch[1]) : 0) || 
                   (sizeMatch ? parseInt(sizeMatch[1]) : 0);
          };
          
          return getSizeParam(b) - getSizeParam(a);
        })[0];
    }
    
    // 如果仍然没有找到合适的URL，返回到原始方法
    if (!finalImageUrl) {
      log(`[${taskId}] 无法找到原图链接，尝试直接使用页面上最大图片`);
      
      finalImageUrl = await page.evaluate(() => {
        const images = Array.from(document.querySelectorAll('img'));
        const sorted = images.sort((a, b) => {
          const areaA = a.width * a.height;
          const areaB = b.width * b.height;
          return areaB - areaA;
        });
        return sorted.length > 0 ? sorted[0].src : null;
      });
    }
    
    if (!finalImageUrl) {
      throw new Error('无法在页面上找到任何合适的图片');
    }
    
    // 确保使用高清版本URL
    if (finalImageUrl.includes('discord') && !finalImageUrl.includes('format=')) {
      finalImageUrl = finalImageUrl.includes('?') ? 
        `${finalImageUrl}&format=original` : 
        `${finalImageUrl}?format=original`;
    }
    
    log(`[${taskId}] 提取到最终图片URL: ${finalImageUrl}`);
    
    // 下载高清图片
    const viewSource = await page.goto(finalImageUrl, { waitUntil: 'networkidle0', timeout: 30000 });
    const buffer = await viewSource.buffer();
    fs.writeFileSync(outputPath, buffer);

    await browser.close();
    log(`[${taskId}] 高清图片已下载到: ${outputPath}`);
    return outputPath;
  } catch (error) {
    log(`[${taskId}] 下载图片失败: ${error.message}`);
    await updateTaskStatus(taskId, 'download_failed', 0, `下载失败: ${error.message}`);
    throw error;
  }
}

// 上传图片到服务器
async function uploadImageToServer(imagePath, taskId) {
  log(`[${taskId}] 开始上传图片: ${imagePath}`);

  try {
    // 获取文件大小
    const stats = fs.statSync(imagePath);
    const fileSizeInBytes = stats.size;
    
    // 如果文件小于0.5MB，使用普通上传
    if (fileSizeInBytes < 0.5 * 1024 * 1024) {
      // 创建form数据
      const form = new FormData();
      form.append('imageFile', fs.createReadStream(imagePath));
      form.append('taskId', taskId);
      form.append('deviceId', 'localpc-downloader'); // 添加设备ID

      // 上传图片
      const response = await apiClient.post('/upload-image', form, {
        headers: {
          ...form.getHeaders(),
          'x-api-key': API_KEY
        }
      });

      log(`[${taskId}] 图片上传成功: ${JSON.stringify(response.data)}`);
      
      // 转换相对路径为完整URL
      if (response.data.success && response.data.imageUrl && response.data.imageUrl.startsWith('/')) {
        response.data.imageUrl = `${SERVER_API_BASE_URL}${response.data.imageUrl}`;
        log(`[${taskId}] 将相对路径转换为完整URL: ${response.data.imageUrl}`);
      }
      
      return response.data;
    } else {
      // 大文件分片上传
      log(`[${taskId}] 文件较大(${(fileSizeInBytes/1024/1024).toFixed(2)}MB)，启用分片上传`);
      
      // 分片大小：0.5MB
      const CHUNK_SIZE = 0.5 * 1024 * 1024;
      const totalChunks = Math.ceil(fileSizeInBytes / CHUNK_SIZE);
      const fileBuffer = fs.readFileSync(imagePath);
      const fileName = path.basename(imagePath);
      
      // 生成随机上传ID
      const uploadId = `upload_${Date.now()}_${Math.floor(Math.random() * 10000)}`;
      
      // 上传每个分片
      for (let i = 0; i < totalChunks; i++) {
        const start = i * CHUNK_SIZE;
        const end = Math.min(fileSizeInBytes, start + CHUNK_SIZE);
        const chunkBuffer = fileBuffer.slice(start, end);
        
        // 不再创建临时文件，改为直接使用Base64编码
        const base64Chunk = chunkBuffer.toString('base64');
        
        // 创建JSON请求数据
        const requestData = {
          taskId,
          uploadId,
          chunkIndex: i,
          totalChunks,
          deviceId: 'localpc-downloader',
          chunk: base64Chunk,
          requestType: 'uploadChunk'
        };
        
        try {
          // 上传分片 - 使用JSON格式
          const response = await apiClient.post('/uploadChunk', requestData, {
            headers: {
              'Content-Type': 'application/json',
              'x-api-key': API_KEY
            },
            maxBodyLength: Infinity,
            maxContentLength: Infinity
          });
          
          // 计算进度（仅用于日志记录）
          const progress = Math.round((i + 1) / totalChunks * 100);
          log(`[${taskId}] 分片 ${i+1}/${totalChunks} 上传成功，总进度: ${progress}%`);
          
          // 删除不必要的状态更新API调用，减少网络请求
          // 服务器已经知道分片上传情况，无需客户端再通知进度
        } catch (error) {
          log(`[${taskId}] 分片 ${i+1}/${totalChunks} 上传失败: ${error.message}`);
          if (error.response) {
            log(`[${taskId}] 错误状态码: ${error.response.status}`);
            log(`[${taskId}] 错误响应数据: ${JSON.stringify(error.response.data)}`);
            throw new Error(`分片上传失败: ${error.response.data.message || error.message}`);
          } else {
            throw new Error(`分片上传失败: ${error.message}`);
          }
        }
      }
      
      // 所有分片上传完成，请求合并
      try {
        const completeRequestData = {
          taskId,
          uploadId,
          totalChunks,
          fileName,
          deviceId: 'localpc-downloader',
          requestType: 'completeUpload'
        };
        
        const completeResponse = await apiClient.post('/completeUpload', completeRequestData, {
          headers: {
            'Content-Type': 'application/json',
            'x-api-key': API_KEY
          },
          maxBodyLength: Infinity,
          maxContentLength: Infinity
        });
        
        log(`[${taskId}] 分片上传完成，合并成功: ${JSON.stringify(completeResponse.data)}`);
        
        // 转换相对路径为完整URL
        if (completeResponse.data.success && completeResponse.data.imageUrl && completeResponse.data.imageUrl.startsWith('/')) {
          completeResponse.data.imageUrl = `${SERVER_API_BASE_URL}${completeResponse.data.imageUrl}`;
          log(`[${taskId}] 将相对路径转换为完整URL: ${completeResponse.data.imageUrl}`);
          
          // 如果有缩略图URL，也需要转换
          if (completeResponse.data.thumbnailUrl && completeResponse.data.thumbnailUrl.startsWith('/')) {
            completeResponse.data.thumbnailUrl = `${SERVER_API_BASE_URL}${completeResponse.data.thumbnailUrl}`;
            log(`[${taskId}] 将缩略图相对路径转换为完整URL: ${completeResponse.data.thumbnailUrl}`);
          }
        }
        
        return completeResponse.data;
      } catch (error) {
        log(`[${taskId}] 合并分片失败: ${error.message}`);
        if (error.response) {
          log(`[${taskId}] 错误状态码: ${error.response.status}`);
          log(`[${taskId}] 错误响应数据: ${JSON.stringify(error.response.data)}`);
          throw new Error(`合并分片失败: ${error.response.status === 404 ? (error.response.data.message || '任务不存在') : (error.response.data.message || error.message)}`);
        } else {
          throw new Error(`合并分片失败: ${error.message}`);
        }
      }
    }
  } catch (error) {
    log(`[${taskId}] 图片上传失败: ${error.message}`);
    throw error;
  }
}

// 通知服务器任务完成
async function notifyTaskComplete(taskId, imageUrl) {
  log(`[${taskId}] 通知服务器任务完成`);

  try {
    const response = await apiClient.post('/api/local-downloader/complete-task', {
      taskId,
      imageUrl,
      deviceId: 'localpc-downloader' // 添加设备ID
    });

    log(`[${taskId}] 通知任务完成成功: ${JSON.stringify(response.data)}`);
    return response.data;
  } catch (error) {
    log(`[${taskId}] 通知任务完成失败: ${error.message}`);
    throw error;
  }
}

// 更新任务状态
async function updateTaskStatus(taskId, status, progress, message) {
  try {
    const response = await apiClient.post('/api/local-downloader/update-task-status', {
      taskId,
      status,
      progress,
      message,
      deviceId: 'localpc-downloader' // 添加设备ID
    });
    return response.data;
  } catch (error) {
    log(`[${taskId}] 更新任务状态失败: ${error.message}`);
    return null;
  }
}

// 处理单个任务
async function processTask(task) {
  const taskId = task.taskId;
  const discordImageUrl = task.discordImageUrl;

  if (!discordImageUrl) {
    log(`[${taskId}] 任务缺少Discord图片URL`);
    await updateTaskStatus(taskId, 'failed', 0, '任务缺少Discord图片URL');
    return;
  }

  try {
    log(`[${taskId}] 开始处理任务: ${discordImageUrl}`);

    // 步骤1: 下载图片
    const imagePath = await downloadDiscordImage(discordImageUrl, taskId);

    // 步骤2: 上传图片到服务器
    const uploadResult = await uploadImageToServer(imagePath, taskId);

    if (!uploadResult.success) {
      throw new Error(`上传失败: ${uploadResult.message}`);
    }

    // 步骤3: 通知服务器任务完成
   // await notifyTaskComplete(taskId, uploadResult.imageUrl);

    // 完成
    log(`[${taskId}] 任务处理完成`);
  } catch (error) {
    log(`[${taskId}] 任务处理失败: ${error.message}`);
    
    // 更新任务状态为失败
    await updateTaskStatus(taskId, 'failed', 0, `处理失败: ${error.message}`);
  }
}

// 清理旧文件
function cleanupOldFiles() {
  try {
    const now = Date.now();
    let count = 0;
    
    fs.readdirSync(DOWNLOAD_DIR).forEach(file => {
      const filePath = path.join(DOWNLOAD_DIR, file);
      const stat = fs.statSync(filePath);
      
      if (now - stat.mtime.getTime() > MAX_FILE_AGE) {
        fs.unlinkSync(filePath);
        count++;
      }
    });
    
    if (count > 0) {
      log(`已清理 ${count} 个过期文件`);
    }
  } catch (error) {
    log(`清理文件失败: ${error.message}`);
  }
}

// 主轮询函数
async function pollForTasks() {
  try {
    const tasks = await getPendingTasks();
    
    if (tasks.length > 0) {
      log(`获取到 ${tasks.length} 个待处理任务`);
      
      // 处理第一个任务
      await processTask(tasks[0]);
    }
  } catch (error) {
    log(`轮询任务失败: ${error.message}`);
  }
  
  // 继续轮询
  setTimeout(pollForTasks, POLL_INTERVAL);
}

// 启动处理
log('开始轮询任务...');
pollForTasks();

// 定期清理旧文件
log('启动定期文件清理...');
setInterval(cleanupOldFiles, CLEANUP_INTERVAL);

// 捕获未处理的异常
process.on('uncaughtException', (err) => {
  log(`未捕获的异常: ${err.message}`);
  log(err.stack);
});

process.on('unhandledRejection', (reason, promise) => {
  log(`未处理的Promise拒绝: ${reason}`);
});